import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
import warnings

# 忽略警告
warnings.filterwarnings("ignore")

# 确保中文显示正常
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 创建输出目录
output_dir = 'top10_charts'
os.makedirs(output_dir, exist_ok=True)

try:
    # 读取CSV文件
    print("开始读取CSV文件...")
    file_path = 'bilibili_weekly_data.csv'
    
    # 尝试不同编码
    for encoding in ['utf-8', 'gbk', 'gb18030']:
        try:
            df = pd.read_csv(file_path, encoding=encoding)
            print(f"使用 {encoding} 编码成功读取文件")
            break
        except UnicodeDecodeError:
            print(f"使用 {encoding} 编码失败，尝试下一种编码")
    
    # 显示基本信息
    print(f"数据总行数: {len(df)}")
    
    # 处理列名中可能的空格
    df.columns = df.columns.str.strip()
    
    # 确保数值列为数值类型
    numeric_columns = ['点赞数', '投币数', '收藏数', '评论数', '弹幕数', '转发数', '播放量']
    for col in numeric_columns:
        if col in df.columns:
            df[col] = pd.to_numeric(df[col], errors='coerce')
    
    # 1. 分区占比饼图 (只展示Top 10分区)
    if '分区' in df.columns:
        print("正在绘制分区占比饼图（Top 10）...")
        
        # 按分区分组并计算视频数量
        partition_count = df['分区'].value_counts().head(10)
        
        # 创建图形
        plt.figure(figsize=(12, 10))
        
        # 设置饼图的颜色
        colors = plt.cm.tab10(np.arange(len(partition_count)) % 10)
        
        # 计算每个分区的百分比
        total = partition_count.sum()
        percentages = [f'{p/total*100:.1f}%' for p in partition_count]
        
        # 绘制饼图
        wedges, texts = plt.pie(
            partition_count, 
            labels=None,
            startangle=90,
            colors=colors,
            shadow=True,
            explode=[0.05] * len(partition_count),  # 稍微分离每个扇形
            wedgeprops={'edgecolor': 'w', 'linewidth': 1}
        )
        
        # 添加图例
        plt.legend(
            wedges, 
            [f'{label} ({count}, {pct})' for label, count, pct in zip(partition_count.index, partition_count, percentages)],
            title="Top 10分区",
            loc="center left",
            bbox_to_anchor=(1, 0, 0.5, 1)
        )
        
        # 添加标题
        plt.title('B站Top 10分区视频数量占比', fontsize=18)
        plt.axis('equal')  # 保证饼图是圆形的
        plt.tight_layout()
        
        # 保存图表
        output_file = f"{output_dir}/top10_partition_count_pie.png"
        plt.savefig(output_file, dpi=300, bbox_inches='tight')
        plt.close()
        print(f"已保存图表: {output_file}")
    
    # 2. 分区播放量饼图 (只展示Top 10分区)
    if '分区' in df.columns:
        print("正在绘制分区播放量饼图（Top 10）...")
        
        # 按分区分组并计算播放量总和
        partition_views = df.groupby('分区')['播放量'].sum().sort_values(ascending=False).head(10)
        
        # 创建图形
        plt.figure(figsize=(12, 10))
        
        # 设置饼图的颜色
        colors = plt.cm.tab10(np.arange(len(partition_views)) % 10)
        
        # 计算每个分区的百分比和播放量（亿）
        total = partition_views.sum()
        percentages = [f'{p/total*100:.1f}%' for p in partition_views]
        views_in_wan = [f'{v/100000000:.3f}亿' for v in partition_views]

        # 绘制饼图
        wedges, texts = plt.pie(
            partition_views, 
            labels=None,
            startangle=90,
            colors=colors,
            shadow=True,
            explode=[0.05] * len(partition_views),  # 稍微分离每个扇形
            wedgeprops={'edgecolor': 'w', 'linewidth': 1}
        )
        
        # 添加图例
        plt.legend(
            wedges, 
            [f'{label} ({view}, {pct})' for label, view, pct in zip(partition_views.index, views_in_wan, percentages)],
            title="Top 10分区",
            loc="center left",
            bbox_to_anchor=(1, 0, 0.5, 1)
        )
        
        # 添加标题
        plt.title('B站Top 10分区播放量占比', fontsize=18)
        plt.axis('equal')  # 保证饼图是圆形的
        plt.tight_layout()
        
        # 保存图表
        output_file = f"{output_dir}/top10_partition_views_pie.png"
        plt.savefig(output_file, dpi=300, bbox_inches='tight')
        plt.close()
        print(f"已保存图表: {output_file}")
    
    # 3. UP主视频数量饼图 (只展示Top 10 UP主)
    if 'UP主' in df.columns:
        print("正在绘制UP主视频数量饼图（Top 10）...")
        
        # 按UP主分组并计算视频数量
        up_count = df['UP主'].value_counts().head(10)
        
        # 创建图形
        plt.figure(figsize=(12, 10))
        
        # 设置饼图的颜色
        colors = plt.cm.tab10(np.arange(len(up_count)) % 10)
        
        # 计算每个UP主的百分比
        total = up_count.sum()
        percentages = [f'{p/total*100:.1f}%' for p in up_count]
        
        # 绘制饼图
        wedges, texts = plt.pie(
            up_count, 
            labels=None,
            startangle=90,
            colors=colors,
            shadow=True,
            explode=[0.05] * len(up_count),  # 稍微分离每个扇形
            wedgeprops={'edgecolor': 'w', 'linewidth': 1}
        )
        
        # 添加图例
        plt.legend(
            wedges, 
            [f'{label} ({count}, {pct})' for label, count, pct in zip(up_count.index, up_count, percentages)],
            title="Top 10 UP主",
            loc="center left",
            bbox_to_anchor=(1, 0, 0.5, 1)
        )
        
        # 添加标题
        plt.title('B站Top 10 UP主视频数量占比', fontsize=18)
        plt.axis('equal')  # 保证饼图是圆形的
        plt.tight_layout()
        
        # 保存图表
        output_file = f"{output_dir}/top10_up_count_pie.png"
        plt.savefig(output_file, dpi=300, bbox_inches='tight')
        plt.close()
        print(f"已保存图表: {output_file}")
    
    # 4. UP主播放量饼图 (只展示Top 10 UP主)
    if 'UP主' in df.columns:
        print("正在绘制UP主播放量饼图（Top 10）...")
        
        # 按UP主分组并计算播放量总和
        up_views = df.groupby('UP主')['播放量'].sum().sort_values(ascending=False).head(10)
        
        # 创建图形
        plt.figure(figsize=(12, 10))
        
        # 设置饼图的颜色
        colors = plt.cm.tab10(np.arange(len(up_views)) % 10)
        
        # 计算每个UP主的百分比和播放量（亿）
        total = up_views.sum()
        percentages = [f'{p/total*100:.1f}%' for p in up_views]
        views_in_wan = [f'{v/100000000:.3f}亿' for v in up_views]
        
        # 绘制饼图
        wedges, texts = plt.pie(
            up_views, 
            labels=None,
            startangle=90,
            colors=colors,
            shadow=True,
            explode=[0.05] * len(up_views),  # 稍微分离每个扇形
            wedgeprops={'edgecolor': 'w', 'linewidth': 1}
        )
        
        # 添加图例
        plt.legend(
            wedges, 
            [f'{label} ({view}, {pct})' for label, view, pct in zip(up_views.index, views_in_wan, percentages)],
            title="Top 10 UP主",
            loc="center left",
            bbox_to_anchor=(1, 0, 0.5, 1)
        )
        
        # 添加标题
        plt.title('B站Top 10 UP主播放量占比', fontsize=18)
        plt.axis('equal')  # 保证饼图是圆形的
        plt.tight_layout()
        
        # 保存图表
        output_file = f"{output_dir}/top10_up_views_pie.png"
        plt.savefig(output_file, dpi=300, bbox_inches='tight')
        plt.close()
        print(f"已保存图表: {output_file}")
    
    # 5. 各指标Top 10水平柱状图
    for metric in numeric_columns:
        if metric in df.columns:
            print(f"正在绘制 {metric} Top 10水平柱状图...")
            
            # 获取前10名数据
            top_data = df.nlargest(10, metric).copy()
            
            # 处理过长的标题
            top_data['短标题'] = top_data['视频标题'].str.slice(0, 20) + '...'
            
            # 创建图形
            plt.figure(figsize=(12, 8))
            
            # 绘制水平柱状图
            bars = plt.barh(top_data['短标题'], top_data[metric], color='skyblue')
            
            # 为每个柱子添加数值标签
            for bar in bars:
                width = bar.get_width()
                plt.text(width * 1.01, bar.get_y() + bar.get_height()/2, 
                        f'{int(width):,}', va='center')
            
            # 添加标题和标签
            plt.title(f'B站视频{metric}排名 Top 10', fontsize=16)
            plt.xlabel(metric, fontsize=12)
            plt.ylabel('视频标题', fontsize=12)
            plt.tight_layout()
            
            # 保存图表
            output_file = f"{output_dir}/top10_{metric}_horizontal.png"
            plt.savefig(output_file, dpi=300)
            plt.close()
            print(f"已保存图表: {output_file}")
    
    print("所有Top 10图表生成完毕！")

except Exception as e:
    print(f"发生错误: {str(e)}")
    import traceback
    traceback.print_exc() 